﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
//using Gxu.Cisco.Common.Models;
using Gxu.Models;
using XCode;

namespace Gxu.Models
{
    /// <summary>菜单</summary>
    public partial class Menus : Entity<Menus>
    {
        #region 对象操作

        /// <summary>验证数据，通过抛出异常的方式提示验证失败。</summary>
        /// <param name="isNew"></param>
        public override void Valid(Boolean isNew)
        {
            // 这里验证参数范围，建议抛出参数异常，指定参数名，前端用户界面可以捕获参数异常并聚焦到对应的参数输入框
            //if (String.IsNullOrEmpty(Name)) throw new ArgumentNullException(_.Name, _.Name.DisplayName + "无效！");
            //if (!isNew && ID < 1) throw new ArgumentOutOfRangeException(_.ID, _.ID.DisplayName + "必须大于0！");

            // 建议先调用基类方法，基类方法会对唯一索引的数据进行验证
            base.Valid(isNew);

            // 在新插入数据或者修改了指定字段时进行唯一性验证，CheckExist内部抛出参数异常
            //if (isNew || Dirtys[__.Name]) CheckExist(__.Name);
            
            if (isNew && !Dirtys[__.CreateDate]) CreateDate = DateTime.Now;
            if (!Dirtys[__.ModifyDate]) ModifyDate = DateTime.Now;
        }

        ///// <summary>首次连接数据库时初始化数据，仅用于实体类重载，用户不应该调用该方法</summary>
        //[EditorBrowsable(EditorBrowsableState.Never)]
        //protected override void InitData()
        //{
        //    base.InitData();

        //    // InitData一般用于当数据表没有数据时添加一些默认数据，该实体类的任何第一次数据库操作都会触发该方法，默认异步调用
        //    // Meta.Count是快速取得表记录数
        //    if (Meta.Count > 0) return;

        //    // 需要注意的是，如果该方法调用了其它实体类的首次数据库操作，目标实体类的数据初始化将会在同一个线程完成
        //    if (XTrace.Debug) XTrace.WriteLine("开始初始化{0}[{1}]数据……", typeof(Menus).Name, Meta.Table.DataTable.DisplayName);

        //    var entity = new Menus();
        //    entity.CreateBy = "abc";
        //    entity.CreateDate = DateTime.Now;
        //    entity.ModifyBy = "abc";
        //    entity.ModifyDate = DateTime.Now;
        //    entity.Remove = true;
        //    entity.RemoveBy = "abc";
        //    entity.RemoveDate = DateTime.Now;
        //    entity.Name = "abc";
        //    entity.ParentIds = "abc";
        //    entity.Description = "abc";
        //    entity.Code = "abc";
        //    entity.Controller = "abc";
        //    entity.Action = "abc";
        //    entity.Parameters = "abc";
        //    entity.Sort = 0;
        //    entity.Render = 0;
        //    entity.Depth = 0;
        //    entity.ChildNum = 0;
        //    entity.URL = "abc";
        //    entity.ICON = "abc";
        //    entity.ParentID = 0;
        //    entity.State = "abc";
        //    entity.IsChild = true;
        //    entity.IsSys = true;
        //    entity.Insert();

        //    if (XTrace.Debug) XTrace.WriteLine("完成初始化{0}[{1}]数据！", typeof(Menus).Name, Meta.Table.DataTable.DisplayName);
        //}


        ///// <summary>已重载。基类先调用Valid(true)验证数据，然后在事务保护内调用OnInsert</summary>
        ///// <returns></returns>
        //public override Int32 Insert()
        //{
        //    return base.Insert();
        //}

        ///// <summary>已重载。在事务保护范围内处理业务，位于Valid之后</summary>
        ///// <returns></returns>
        //protected override Int32 OnInsert()
        //{
        //    return base.OnInsert();
        //}
        #endregion

        #region 扩展属性

        private Menus _parent;
        public Menus Parent
        {
            get
            {
                if (_parent == null)
                {
                    _parent = Menus.FindByID(this.ParentID);
                }
                return _parent;
            }
            set
            {
                _parent = value;
            }
        }
        private string _IsChecked;
        /// <summary>
        /// 所有关联的操作ID集合
        /// </summary>
        public string ActionIDs
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_IsChecked))
                {
                    var mas = MenuActionMap.FindAll("MenuID", this.ID);
                    List<long> ActionIDs = new List<long>();
                    if (mas != null && mas.Count > 0)
                    {
                        foreach (MenuActionMap ma in mas)
                        {
                            ActionIDs.Add(ma.ActionID);
                        }
                    }
                    _IsChecked = string.Join(",", ActionIDs);
                }
                return _IsChecked;
            }
            set
            {
                _IsChecked = value;
            }
        }

        private List<string> _parents = null;

        /// <summary>
        /// 所有父项
        /// </summary>
        public IList<string> Parents
        {
            get
            {
                if (_parents == null)
                {
                    if (!string.IsNullOrEmpty(ParentIds))
                    {
                        List<string> ps = new List<string>();
                        string[] sp = ParentIds.Split(",");
                        foreach (var item in sp)
                        {
                            ps.Add(item);
                        }
                        _parents = ps;
                    }
                    else if (ID > 0)
                        _parents = new List<string>(1) { ID.ToString() };
                }
                return _parents;
            }
            set
            {
                if (value != null)
                {
                    int index = 0;
                    List<string> list = new List<string>();
                    foreach (string item in value)
                    {
                        if (!string.IsNullOrEmpty(item) && !item[0].Equals(",")
                                && !list.Contains(item))
                        {
                            if (index > 0)
                                list.Add(",".ToString());
                            list.Add(item);
                            index++;
                        }
                    }
                    _parents = list;
                    Depth = index;
                    ParentIds = string.Concat(_parents);
                }
            }
        }

        #endregion

        #region 扩展查询
        /// <summary>根据ID查找</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public static Menus FindByID(Int64 id)
        {
            if (Meta.Count >= 1000)
                return Find(_.ID, id);
            else // 实体缓存
                return Meta.Cache.Entities.Find(f=>f.ID== id);
            // 单对象缓存
            //return Meta.SingleCache[id];
        }
        #endregion

        #region 高级查询
        // 以下为自定义高级查询的例子

        ///// <summary>
        ///// 查询满足条件的记录集，分页、排序
        ///// </summary>
        ///// <param name="key">关键字</param>
        ///// <param name="orderClause">排序，不带Order By</param>
        ///// <param name="startRowIndex">开始行，0表示第一行</param>
        ///// <param name="maximumRows">最大返回行数，0表示所有行</param>
        ///// <returns>实体集</returns>
        //[DataObjectMethod(DataObjectMethodType.Select, true)]
        //public static EntityList<Menus> Search(String key, String orderClause, Int32 startRowIndex, Int32 maximumRows)
        //{
        //    return FindAll(SearchWhere(key), orderClause, null, startRowIndex, maximumRows);
        //}

        ///// <summary>
        ///// 查询满足条件的记录总数，分页和排序无效，带参数是因为ObjectDataSource要求它跟Search统一
        ///// </summary>
        ///// <param name="key">关键字</param>
        ///// <param name="orderClause">排序，不带Order By</param>
        ///// <param name="startRowIndex">开始行，0表示第一行</param>
        ///// <param name="maximumRows">最大返回行数，0表示所有行</param>
        ///// <returns>记录数</returns>
        //public static Int32 SearchCount(String key, String orderClause, Int32 startRowIndex, Int32 maximumRows)
        //{
        //    return FindCount(SearchWhere(key), null, null, 0, 0);
        //}

        /// <summary>构造搜索条件</summary>
        /// <param name="key">关键字</param>
        /// <returns></returns>
        private static String SearchWhere(String key)
        {
            // WhereExpression重载&和|运算符，作为And和Or的替代
            // SearchWhereByKeys系列方法用于构建针对字符串字段的模糊搜索
            var exp = SearchWhereByKeys(key, null);

            // 以下仅为演示，Field（继承自FieldItem）重载了==、!=、>、<、>=、<=等运算符（第4行）
            //if (userid > 0) exp &= _.OperatorID == userid;
            //if (isSign != null) exp &= _.IsSign == isSign.Value;
            //if (start > DateTime.MinValue) exp &= _.OccurTime >= start;
            //if (end > DateTime.MinValue) exp &= _.OccurTime < end.AddDays(1).Date;

            return exp;
        }
        #endregion

        #region 扩展操作
        /// <summary>
        /// 菜单转化
        /// </summary>
        /// 
        public static List<dynamic> ToTreeEntities(List<Menus> menusList, long pId = 0)
            => menusList.Where(w => w.ParentID == pId)
                .Select(n =>
                {
                    var childNodes = ToTreeEntities(menusList, n.ID);
                    object menu = new
                    {
                        complete = true,
                        id = n.ID.ToString(),
                        hasChildren = childNodes.Count > 0,
                        name = n.Name,
                        value = n.URL ?? "",
                        url = n.URL,
                        target = "frmright",
                        showProgess = false,
                        parentId = n.ParentID.ToString(),
                        ChildNodes = childNodes
                    };
                    return menu;
                }).ToList();
        #endregion

        #region 业务
        #endregion
    }
}